#pragma once

#include <assert.h>

namespace Json
{
    //-----------------------------------------------------
    //----- Deserializer ----------------------------------
    //-----------------------------------------------------

    class Deserializer
    {
    };

    void serialize(Deserializer & coder, Node & node, std::string & r)
    {
        r = node.toString();
    }

    void serialize(Deserializer & coder, Node & node, double & r)
    {
        r = node;
    }

    void serialize(Deserializer & coder, Node & node, int & r)
    {
        r = (int)node.toNumber();
    }

    void serialize(Deserializer & coder, Node & node, bool & r)
    {
        r = node.toBool();
    }

    template<typename V>
    void serialize(Deserializer & coder, Node & node, std::vector<V> & value)
    {
        int n = node.size();
        value.resize(n);
        for (int i = 0; i < n; i++)
        {
            serialize(coder, node[i], value[i]);
        }
    }

    template<typename K, typename V>
    void serialize(Deserializer & coder, Node & node, std::map<K, V> & value)
    {
        std::vector<std::pair<K, V>> pairs;
        serialize(coder, node, pairs);
        for (int i = 0; i < (int) pairs.size(); i++)
        {
            value[pairs[i].first] = pairs[i].second;
        }
    }

    template<typename C, typename K, typename V>
    void serialize(C & coder, Node & node, std::pair<K, V> & value)
    {
        serialize(coder, node["first"], value.first);
        serialize(coder, node["second"], value.second);
    }


    template<typename V>
    void serialize(Deserializer & coder, Node & node, boost::shared_ptr<V> & value)
    {
        V * ptr;
        serialize(coder, node, ptr);
        value.reset(ptr);
    }

    //-----------------------------------------------------
    //----- Serializer ------------------------------------
    //-----------------------------------------------------

    class Serializer
    {
    };

    void serialize(Serializer & coder, Node & node, std::string & r)
    {
        node = r;
    }

    void serialize(Serializer & coder, Node & node, double & r)
    {
        node = r;
    }

    void serialize(Serializer & coder, Node & node, bool & r)
    {
        node = r;
    }

    void serialize(Serializer & coder, Node & node, int & r)
    {
        node = r;
    }

    template<typename K, typename V>
    void serialize(Serializer & coder, Node & node, std::map<K, V> & r)
    {
        std::vector<std::pair<K, V>> pairs;
        for (std::map<K, V>::const_iterator it = r.begin(); it != r.end(); it++)
        {
            pairs.push_back(std::pair<K, V>(it->first, it->second));
        }
        serialize(coder, node, pairs);
    }

    template<typename V>
    void serialize(Serializer & coder, Node & node, std::vector<V> & r)
    {
        node.clear();
        for (int i = 0; i < (int) r.size(); i++)
        {
            serialize(coder, node[i], r[i]);
        }
    }
}